﻿/* Copyright (C) 2008-2009 Jorson.WHY
 * All right reserved
 * ********** Project Info ***********
 * Project Name : Common
 * NameSpace : MyLibrary.Security
 * Filename : EncryptHelper
 * Create Time : 4/10/2008 4:21:30 PM
 * ********** Environment Info *******
 * Machine Name : EA-01504-11220
 * CLR Version : 2.0.50727.1433
 */
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.Xml;
using System.IO;


namespace MyLibrary.Security
{
    /// <summary>
    /// 简单加密类
    /// </summary>
    public class EncryptHelper
    {
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <param name="encoding">编码</param>
        /// <returns>加密结果</returns>
        public static string MD5Encrypt(string source,Encoding encoding)
        {
            MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
            byte[] bytes = encoding.GetBytes(source);
            byte[] bytes2 = md5.ComputeHash(bytes);
            string result = String.Empty;
            for (int i = 0; i < bytes2.Length; i++)
            {
                string str2 = bytes2[i].ToString("x");
                if (str2.Length == 1)
                    str2 = "0" + str2;
                result += str2;
            }
            return result;
        }
        /// <summary>
        /// MD5加密
        /// </summary>
        /// <param name="source">原始字符串</param>
        /// <returns>加密结果</returns>
        public static string MD5Encrypt(string source)
        {
            return MD5Encrypt(source, Encoding.Default);
        }
    }

    /// <summary>
    /// RSA加密服务接口
    /// </summary>
    public interface IRSACryptService
    {
        byte[] Decrypt(byte[] buffer, string pvk);
        byte[] Encrypt(byte[] buffer, string puk);
    }

    /// <summary>
    /// 对称加密服务接口
    /// </summary>
    public interface ISymmetricCryptService
    {
        byte[] Decrypt(ArraySegment<byte> buffer);
        byte[] Encrypt(ArraySegment<byte> buffer);
        SymmetricAlgorithm SA { get; set; }
    }

    /// <summary>
    /// RSA加密服务基类
    /// </summary>
    public class RSACryptServiceBaseClass : IRSACryptService
    {
        protected RSACryptServiceBaseClass()
        {
        }

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();

        /// <summary>
        /// 解密
        /// </summary>
        public byte[] Decrypt(byte[] buffer, string pvk)
        {
            rsa.FromXmlString(pvk);
            return rsa.Decrypt(buffer, false);
        }

        /// <summary>
        /// 加密
        /// </summary>
        public byte[] Encrypt(byte[] buffer, string puk)
        {
            rsa.FromXmlString(puk);
            return rsa.Encrypt(buffer, false);
        }
    }

    public class RSAKey
    {
        string xmlString;
        public string XmlString
        {
            get { return xmlString; }
        }

        public string PublicKey
        {
            get 
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                rsa.FromXmlString(xmlString);
                return rsa.ToXmlString(false);
            }
        }

        public RSAKey(string xmlString)
        {
            this.xmlString = xmlString;    
        }

        public static RSAKey CreateKey()
        {
            RSAKeyValue rsaKey = new RSAKeyValue();
            return new RSAKey(rsaKey.Key.ToXmlString(true));
        }
    }

    /// <summary>
    /// 对称加密服务基类
    /// </summary>
    public class SymmetricCryptServiceBaseClass : ISymmetricCryptService
    {
        SymmetricAlgorithm sa;
        public SymmetricAlgorithm SA
        {
            get { return sa; }
            set { sa = value; }
        }

        public SymmetricCryptServiceBaseClass()
        {
            SA = new TripleDESCryptoServiceProvider();
            SA.Key = SecurityCommon.GenerateBytes(SA.KeySize / 8);
            SA.IV = SecurityCommon.GenerateBytes(SA.IV.Length);

            SA.Mode = CipherMode.CBC;
            SA.Padding = PaddingMode.ISO10126;
        }

        /// <summary>
        /// 加密
        /// </summary>
        public byte[] Encrypt(ArraySegment<byte> buffer)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (CryptoStream cs = new CryptoStream(ms,sa.CreateEncryptor(),CryptoStreamMode.Write))
                {
                    cs.Write(buffer.Array,buffer.Offset,buffer.Count);
                    cs.FlushFinalBlock();
                    return ms.ToArray();
                }
            }
        }

        /// <summary>
        /// 解密
        /// </summary>
        public byte[] Decrypt(ArraySegment<byte> buffer)
        {
            using (MemoryStream ms = new MemoryStream(buffer.Array, buffer.Offset, buffer.Count))
            {
                using (CryptoStream cs = new CryptoStream(ms, sa.CreateDecryptor(), CryptoStreamMode.Read))
                {
                    using (BinaryReader br = new BinaryReader(cs))
                    {
                        return br.ReadBytes(8192);
                    }
                }
            }
        }
    }

    /// <summary>
    /// 加密用公有方法
    /// </summary>
    public static class SecurityCommon
    {
        /// <summary>
        /// 随机生成指定长度的Byte
        /// </summary>
        /// <param name="byteLength">生成Byte数组的长度</param>
        /// <returns>Byte数组</returns>
        public static byte[] GenerateBytes(int byteLength)
        {
            byte[] buff = new byte[byteLength];
            RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
            
            rng.GetBytes(buff);
            return buff;
        }

        /// <summary>
        /// MD5加密
        /// </summary>
        public static string MD5(string org)
        {
            byte[] buffer = MD5CryptoServiceProvider.Create().ComputeHash(Encoding.Unicode.GetBytes(org));
            return Convert.ToBase64String(buffer);
        }
    }
}
